package com.inspinia.base.util;

import com.inspinia.base.common.model.NameCodeEnum;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * Created by jcq on 2016/6/15.
 */
public class ExcelUtils {

    /**
     * 数字格式化
     */
    private static NumberFormat format = NumberFormat.getInstance();

    /**
     * @param obj 操作的对象
     * @param att 操作的属性
     */
    public static Object getter(Object obj, String att) {
        StringBuffer sb = new StringBuffer();
        try {
            String[] attrs = att.split("&");
            for (String str : attrs) {
                Method method = obj.getClass().getMethod("get" + str);
                Object object = method.invoke(obj);
                if (object instanceof NameCodeEnum) {
                    sb.append(((NameCodeEnum) object).getName());
                } else if (object instanceof Date) {
                    try {
                        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        sb.append(df.format(object));
                    } catch (Exception e) {
                    }
                } else {
                    sb.append(method.invoke(obj));
                }
                sb.append("/");
            }
        } catch (Exception e) {
            return null;
        }
        return sb == null ? "" : sb.substring(0, sb.length() - 1);
    }

    /*
    * 列头单元格样式
    */
    public static HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {

        // 设置字体
        HSSFFont font = workbook.createFont();
        //设置字体大小
        font.setFontHeightInPoints((short) 11);
        //字体加粗
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        //设置字体名字
        font.setFontName("Courier New");
        //设置样式;
        HSSFCellStyle style = workbook.createCellStyle();
        //设置底边框;
        style.setBorderBottom(CellStyle.BORDER_THIN);
        //设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        //设置左边框;
        style.setBorderLeft(CellStyle.BORDER_THIN);
        //设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        //设置右边框;
        style.setBorderRight(CellStyle.BORDER_THIN);
        //设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        //设置顶边框;
        style.setBorderTop(CellStyle.BORDER_THIN);
        //设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(false);
        //设置水平对齐的样式为居中对齐;
        style.setAlignment(CellStyle.ALIGN_CENTER);
        //设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);

        return style;

    }

    /*
     * 列数据信息单元格样式
     */
    public static HSSFCellStyle getStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        //设置字体大小
        //font.setFontHeightInPoints((short)10);
        //字体加粗
        //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        //设置字体名字
        font.setFontName("Courier New");
        //设置样式;
        HSSFCellStyle style = workbook.createCellStyle();
        //设置底边框;
        style.setBorderBottom(CellStyle.BORDER_THIN);
        //设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        //设置左边框;
        style.setBorderLeft(CellStyle.BORDER_THIN);
        //设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        //设置右边框;
        style.setBorderRight(CellStyle.BORDER_THIN);
        //设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        //设置顶边框;
        style.setBorderTop(CellStyle.BORDER_THIN);
        //设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(false);
        //设置水平对齐的样式为居中对齐;
        style.setAlignment(CellStyle.ALIGN_CENTER);
        //设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        return style;
    }

    /*
  * 列头单元格样式
  */
    public static CellStyle getColumnTopStyle(Workbook workbook) {

        // 设置字体
        Font font = workbook.createFont();
        workbook.createFont();
        //设置字体大小
        font.setFontHeightInPoints((short) 11);
        //字体加粗
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        //设置字体名字
        font.setFontName("Courier New");
        //设置样式;
        CellStyle style = workbook.createCellStyle();
        //设置底边框;
        style.setBorderBottom(CellStyle.BORDER_THIN);
        //设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        //设置左边框;
        style.setBorderLeft(CellStyle.BORDER_THIN);
        //设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        //设置右边框;
        style.setBorderRight(CellStyle.BORDER_THIN);
        //设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        //设置顶边框;
        style.setBorderTop(CellStyle.BORDER_THIN);
        //设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(false);
        //设置水平对齐的样式为居中对齐;
        style.setAlignment(CellStyle.ALIGN_CENTER);
        //设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        return style;
    }


    /*
     * 列数据信息单元格样式
     */
    public static CellStyle getStyle(Workbook workbook) {
        // 设置字体
        Font font = workbook.createFont();
        //设置字体大小
        //font.setFontHeightInPoints((short)10);
        //字体加粗
        //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        //设置字体名字
        font.setFontName("Courier New");
        //设置样式;
        CellStyle style = workbook.createCellStyle();
        //设置底边框;
        style.setBorderBottom(CellStyle.BORDER_THIN);
        //设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        //设置左边框;
        style.setBorderLeft(CellStyle.BORDER_THIN);
        //设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        //设置右边框;
        style.setBorderRight(CellStyle.BORDER_THIN);
        //设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        //设置顶边框;
        style.setBorderTop(CellStyle.BORDER_THIN);
        //设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(false);
        //设置水平对齐的样式为居中对齐;
        style.setAlignment(CellStyle.ALIGN_CENTER);
        //设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        return style;
    }

    /**
     * 当点击下载前，触发一次，删除5分钟前创建的文件
     *
     * @param floder
     */
    public static void deleteFiles(String floder) {
        long value = 300000L;//5分钟的time值
        long currentValue = new Date().getTime();
        File file = new File(floder);
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                String fileName = f.getName();
                String date = fileName.substring(fileName.lastIndexOf("_") + 1, fileName.lastIndexOf("."));
                long fileValue = Long.valueOf(date);
                if (currentValue - fileValue >= value) {
                    f.delete();
                }
            }
        }
    }

    /**
     * 根据文件路径读取excel文件，默认读取第0个sheet
     *
     * @param excelPath   excel的路径
     * @param skipRows    需要跳过的行数
     * @param columnCount 列数量
     * @return List<String[]> 集合中每一个元素是一个数组，按单元格索引存储每个单元格的值，一个元素可以封装成一个需要的java bean
     * @throws Exception
     * @Author : ll. create at 2016年4月14日 上午9:28:39
     */
    public static List<String[]> readExcel(String excelPath, int skipRows, int columnCount)
            throws Exception {
        return readExcel(excelPath, skipRows, columnCount, 0, null);
    }

    /**
     * 根据文件路径读取excel文件的指定sheet
     *
     * @param excelPath   excel的路径
     * @param skipRows    需要跳过的行数
     * @param columnCount 列数量
     * @param sheetNo     要读取的sheet的索引，从0开始
     * @return List<String[]> 集合中每一个元素是一个数组，按单元格索引存储每个单元格的值，一个元素可以封装成一个需要的java bean
     * @throws Exception
     * @Author : ll. create at 2016年4月14日 上午9:28:39
     */
    public static List<String[]> readExcel(String excelPath, int skipRows, int columnCount,
                                           int sheetNo) throws Exception {
        return readExcel(excelPath, skipRows, columnCount, sheetNo, null);
    }

    /**
     * 根据文件路径读取excel文件的指定sheet，并封装空值单位各的坐标，默认读取第0个sheet
     *
     * @param excelPath                 excel的路径
     * @param skipRows                  需要跳过的行数
     * @param columnCount               列数量
     * @param noneCellValuePositionList 存储空值的单元格的坐标，每个坐标以x-y的形式拼接，如2-5表示第二行第五列
     * @return List<String[]> 集合中每一个元素是一个数组，按单元格索引存储每个单元格的值，一个元素可以封装成一个需要的java bean
     * @throws Exception
     * @Author : ll. create at 2016年4月14日 上午9:28:39
     */
    public static List<String[]> readExcel(String excelPath, int skipRows, int columnCount,
                                           List<String> noneCellValuePositionList) throws Exception {
        return readExcel(excelPath, skipRows, columnCount, 0, noneCellValuePositionList);
    }

    /**
     * 根据文件路径读取excel文件的指定sheet，并封装空值单位各的坐标，默认读取第0个sheet
     *
     * @param excelPath                           excel的路径
     * @param skipRows                            需要跳过的行数
     * @param columnCount                         列数量
     * @param columnNumberForSkipValueValidateSet 不需要做空值验证的列的索引集合
     * @param noneCellValuePositionList           存储空值的单元格的坐标，每个坐标以x-y的形式拼接，如2-5表示第二行第五列
     * @return List<String[]> 集合中每一个元素是一个数组，按单元格索引存储每个单元格的值，一个元素可以封装成一个需要的java bean
     * @throws Exception
     * @Author : ll. create at 2016年4月14日 上午9:28:39
     */
    public static List<String[]> readExcel(String excelPath, int skipRows, int columnCount,
                                           Set<Integer> columnNumberForSkipValueValidateSet,
                                           List<String> noneCellValuePositionList) throws Exception {
        return readExcel(excelPath, skipRows, columnCount, 0, columnNumberForSkipValueValidateSet,
                noneCellValuePositionList);
    }

    /**
     * 根据文件路径读取excel文件的指定sheet，并封装空值单位各的坐标
     *
     * @param excelPath                 excel的路径
     * @param skipRows                  需要跳过的行数
     * @param columnCount               列数量
     * @param sheetNo                   要读取的sheet的索引，从0开始
     * @param noneCellValuePositionList 存储空值的单元格的坐标，每个坐标以x-y的形式拼接，如2-5表示第二行第五列
     * @return List<String[]> 集合中每一个元素是一个数组，按单元格索引存储每个单元格的值，一个元素可以封装成一个需要的java bean
     * @throws Exception
     * @Author : ll. create at 2016年4月14日 上午9:28:39
     */
    public static List<String[]> readExcel(String excelPath, int skipRows, int columnCount,
                                           int sheetNo, List<String> noneCellValuePositionList)
            throws Exception {
        return readExcel(excelPath, skipRows, columnCount, sheetNo, null, noneCellValuePositionList);
    }

    /**
     * 根据文件路径读取excel文件的指定sheet，并封装空值单位各的坐标
     *
     * @param excelPath                           excel的路径
     * @param skipRows                            需要跳过的行数
     * @param columnCount                         列数量
     * @param sheetNo                             要读取的sheet的索引，从0开始
     * @param columnNumberForSkipValueValidateSet 不需要做空值验证的列的索引集合
     * @param noneCellValuePositionList           存储空值的单元格的坐标，每个坐标以x-y的形式拼接，如2-5表示第二行第五列
     * @return List<String[]> 集合中每一个元素是一个数组，按单元格索引存储每个单元格的值，一个元素可以封装成一个需要的java bean
     * @throws Exception
     * @Author : ll. create at 2016年4月14日 上午9:28:39
     */
    public static List<String[]> readExcel(String excelPath, int skipRows, int columnCount,
                                           int sheetNo,
                                           Set<Integer> columnNumberForSkipValueValidateSet,
                                           List<String> noneCellValuePositionList) throws Exception {

        if (StringUtils.isBlank(excelPath)) {
            return new ArrayList<String[]>();
        }
        boolean isExcel2007 = false;
        FileInputStream is = new FileInputStream(new File(excelPath));
        if (excelPath.endsWith(".xlsx")) {
            isExcel2007 = true;
        }
        Workbook wb = null;
        if (isExcel2007) {
            wb = new XSSFWorkbook(is);
        } else {
            wb = new HSSFWorkbook(is);
        }
        List<String[]> list = new ArrayList<String[]>();
        Sheet sheet = wb.getSheetAt(sheetNo);
        // 得到总共的行数
        int rowNum = sheet.getLastRowNum();
        try {
            for (int i = skipRows; i <= rowNum; i++) {
                String[] vals = new String[columnCount];
                Row row = sheet.getRow(i);
                if (null == row) {
                    continue;
                }
                for (int j = 0; j < columnCount; j++) {
                    Cell cell = row.getCell(j);
                    String val = getStringCellValue(cell);

                    // 没有需要跳过校验的列索引
                    if (CollectionUtils.isEmpty(columnNumberForSkipValueValidateSet)) {
                        if (noneCellValuePositionList != null && StringUtils.isBlank(val)) {
                            // 封装空值单元格的坐标
                            noneCellValuePositionList.add((i + 1) + "-" + j);
                        }
                    } else {
                        // 如果需要校验空值的单元格、当前列索引不在需要跳过校验的索引集合中
                        if (noneCellValuePositionList != null && StringUtils.isBlank(val)
                                && !columnNumberForSkipValueValidateSet.contains(j)) {
                            // 封装空值单元格的坐标
                            noneCellValuePositionList.add((i + 1) + "-" + j);
                        }
                    }

                    vals[j] = val;
                }
                list.add(vals);
            }
        } catch (Exception e) {
            throw new RuntimeException("Excel解析失败");
        } finally {
            is.close();
        }
        return list;
    }

    /**
     * 获取单元格数据内容为字符串类型的数据
     *
     * @param cell Excel单元格{@link Cell}
     * @return 单元格数据内容（可能是布尔类型等，强制转换成String）
     * @Author : ll. create at 2016年4月14日 上午9:53:07
     */
    private static String getStringCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        String strCell = "";
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_STRING:
                strCell = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_NUMERIC:
                strCell = String.valueOf(format.format(cell.getNumericCellValue()))
                        .replace(",", "");
                break;
            case Cell.CELL_TYPE_BOOLEAN:
                strCell = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_BLANK:
                strCell = "";
                break;
            default:
                strCell = "";
                break;
        }
        if (StringUtils.isBlank(strCell)) {
            return "";
        }

        return strCell;
    }
}